package org.phalanx.gwt.client.graphics;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import org.phalanx.gwt.client.graphics.map.MapCoordinates;
import org.phalanx.gwt.client.graphics.map.PhalanxMap;
import org.phalanx.gwt.client.graphics.units.PhalanxMapUnit;
import org.phalanx.gwt.client.graphics.units.PhalanxMapUnitMatrix;
import org.phalanx.gwt.client.shared.OnLoadEvent;
import org.phalanx.gwt.client.shared.PresentationListener;
import org.phalanx.gwt.client.shared.WebPresentable;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.widgetideas.client.GlassPanel;

public class PhalanxGameMapView extends PhalanxWebMapView implements Command{
	private PhalanxMapUnitMatrix uMat;
	private ArrayList<MapCoordinates> visibilityTable;
	private ArrayList<Widget> unitWidgetTable;
	private PresentationListener pListener;
	private Integer gameId = -1;
	
	public PhalanxGameMapView(PhalanxMap map, PhalanxMapUnitMatrix uMat, Integer l, Integer w) {
		super(map, l, w);
		setUnitMatrix(uMat);
		visibilityTable = new ArrayList<MapCoordinates>();
		unitWidgetTable = new ArrayList<Widget>();
		pListener = new PresentationListener();
		this.setDrawBuildPoints(false);
	}
	
	public void setVisiblityToTable(MapCoordinates c){
		if (!visibilityTable.contains(c)){
			visibilityTable.add(c);
		}
	}
	
	public void removeVisibilityFromTable(MapCoordinates c){
		if (visibilityTable.contains(c)){
			visibilityTable.remove(c);
		}
	}
	
	public void clearVisibilityTable(){
		visibilityTable.clear();
	}
	
	public void clearUnits(){
		Iterator<Widget> i = unitWidgetTable.iterator();
		
		while(i.hasNext()){
			Widget unitWidget = i.next();
			this.remove(unitWidget);
		}
	}
	
	
	
	public void renderUnits() {
		clearUnits();
		
		Integer getTileWidthCount = getMapTileX();
		Integer getTileLengthCount = getMapTileY();
		Integer getCenterPosW = getCenterPosTile(getTileWidthCount);
		Integer getCenterPosL = getCenterPosTile(getTileLengthCount);
		
		if ((this.getXPos() - getCenterPosW) <= 0){
			this.setCoordinates(getCenterPosW, this.getYPos());
		}
		if (this.getYPos() - getCenterPosL <= 0){
			this.setCoordinates(this.getXPos(), getCenterPosL);
		}
		int startPointY = currentY - getCenterPosL;
		int startPointX = currentX - getCenterPosW;
		
		int endPointY = startPointY + getTileLengthCount > this.getMap().getMapLength() ?
				this.getMap().getMapLength() : startPointY + getTileLengthCount;
		int endPointX = startPointX + getTileWidthCount > this.getMap().getMapWidth() ?
				this.getMap().getMapWidth() : startPointX + getTileWidthCount;
		
		for (int i = startPointY; i < endPointY; i++){
			for (int j = startPointX; j < endPointX; j++){
				drawGameUnit(j,i);
				drawFogOfWar(j,i);
			}
		}
	}
	
	protected void drawGameUnit(int x, int y){
		Integer pixelPointX = getPixelPointx(x);
		Integer pixelPointY = getPixelPointy(y);
		MapCoordinates c = new MapCoordinates(x ,y);
		
		PhalanxMapUnit unit = getUnitMatrix().getUnitAt(c);
		
		if (pMap.isBounds(c)){
			if (unit != null){
				Image unitImage = new Image();
				
				String refString = "/PhalanxServlet/ServerInstance?context=mapresource&gameid=" + gameId 
				+ "&gameunit=" + unit.getUnitName();
				
				unitImage.setUrl(refString);
				
				rehashImagesForZoom(unitImage);
				
				unitWidgetTable.add(unitImage);
				
				
				this.add(unitImage, pixelPointX, pixelPointY);
			}
		}
	}
	
	protected void drawFogOfWar(int x, int y){
		Integer pixelPointX = getPixelPointx(x);
		Integer pixelPointY = getPixelPointy(y);
		
		MapCoordinates c = new MapCoordinates(x, y);
		
		GlassPanel fog = new GlassPanel(false);
		fog.setWidth(this.getTileSize() + "px");
		fog.setHeight(this.getTileSize() + "px");
		
		
		if (!visibilityTable.contains(c) && pMap.isBounds(c)){
			this.add(fog, pixelPointX, pixelPointY);
			unitWidgetTable.add(fog);
		}
	}

	public void setUnitMatrix(PhalanxMapUnitMatrix uMat) {
		this.uMat = uMat;
	}

	public PhalanxMapUnitMatrix getUnitMatrix() {
		return uMat;
	}

	@Override
	public void renderMap() {
		OnLoadEvent e = new OnLoadEvent("rendermap");
		pListener.setLoadingEvent(e);
		
		DeferredCommand.addCommand(this);
	}
	
	public void addPresentationListener(WebPresentable wP){
		pListener.addPresentationPanelListener(wP);
	}

	@Override
	public void execute() {
		super.renderMap();
		this.renderUnits();
		OnLoadEvent e = new OnLoadEvent("rendermap");
		pListener.setLoadedEvent(e);
	}

	public void setGameId(Integer gameName) {
		this.gameId = gameName;
	}

	public Integer getGameId() {
		return gameId;
	}
}
